rajkhanke commited on
Commit
e3d2211
·
verified ·
1 Parent(s): ed946ba

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -84
app.py CHANGED
@@ -1,20 +1,29 @@
1
- import threading, time
2
- from flask import Flask, render_template, request, jsonify, Response
 
 
3
  import requests
 
4
  from bs4 import BeautifulSoup
5
  from flask_caching import Cache
6
 
7
  app = Flask(__name__)
8
 
9
- # Configure caching here we use a simple in-memory cache.
10
- # In production you might use Redis or another robust backend.
11
  app.config['CACHE_TYPE'] = 'SimpleCache'
12
  app.config['CACHE_DEFAULT_TIMEOUT'] = 300 # Cache responses for 5 minutes
13
  cache = Cache(app)
14
 
15
- # Global variables for pre-fetched image data
16
- cached_image = None
17
- cached_mimetype = None
 
 
 
 
 
 
 
18
 
19
  # Internal mapping of crops to pests (for the form)
20
  CROP_TO_PESTS = {
@@ -46,43 +55,14 @@ CROP_MAPPING = {
46
 
47
  # Map our internal pest names to external page values per crop.
48
  PEST_MAPPING = {
49
- "Cotton": {
50
- "FallArmyWorm": "71"
51
- },
52
- "Gram": {
53
- "H.armigera": "72",
54
- "Wilt": "73"
55
- },
56
- "Maize": {
57
- "FallArmyWorm": "74"
58
- },
59
- "Rice": {
60
- "Blast": "75",
61
- "GallMidge": "76",
62
- "YSB": "77",
63
- "PlantHopper": "78",
64
- "BlueBeetle": "79",
65
- "BacterialLeafBlight": "80"
66
- },
67
- "Soybean": {
68
- "Girdlebeetle": "81",
69
- "H.armigera": "82",
70
- "Semilooper": "83",
71
- "Spodoptera": "84",
72
- "StemFLy": "85"
73
- },
74
- "Tur": {
75
- "Wilt": "86",
76
- "Webbed_Leaves": "87",
77
- "Pod_damage": "88"
78
- },
79
- "Sugarcane": {
80
- "FallArmyGrub": "89",
81
- "WhiteGrub": "90"
82
- },
83
- "Sorgum": {
84
- "FallArmyWorm": "91"
85
- }
86
  }
87
 
88
  # Parameter codes and labels for the final image URL
@@ -103,13 +83,13 @@ def index():
103
  week = request.args.get('week', '')
104
  param = request.args.get('param', '')
105
 
106
- image_url = ""
107
  if crop and pest and year and week and param:
108
  # Build the external image URL (using HTTP)
109
  base_url = f"http://www.icar-crida.res.in:8080/naip/gisimages/{crop}/{year}/{pest}_"
110
  external_image_url = f"{base_url}{param}{week}.jpg"
111
- # Build our proxy URL so that the image is served via our app
112
- image_url = f"/fast-proxy?url={external_image_url}"
113
 
114
  return render_template('index.html',
115
  crops=list(CROP_TO_PESTS.keys()),
@@ -121,8 +101,9 @@ def index():
121
  selected_year=year,
122
  selected_week=week,
123
  selected_param=param,
124
- image_url=image_url)
125
 
 
126
  @app.route('/fetch_weeks')
127
  @cache.cached(timeout=300, query_string=True)
128
  def fetch_weeks():
@@ -153,48 +134,27 @@ def fetch_weeks():
153
  weeks = [str(i) for i in range(1, 53)]
154
  return jsonify({"weeks": weeks})
155
 
156
- # This endpoint now uses a background-prefetched image.
157
- @app.route('/fast-proxy')
158
- def fast_proxy():
159
- global cached_image, cached_mimetype
160
- # If the "url" parameter doesn't match our cached URL, you might consider triggering a prefetch update.
161
  external_url = request.args.get('url')
162
- if cached_image and external_url == prefetch_image.cached_url:
163
- return Response(cached_image, mimetype=cached_mimetype)
 
 
 
 
164
  else:
165
- # If no pre-fetched image is available, fall back to a direct fetch.
166
  try:
167
  resp = requests.get(external_url, timeout=10)
168
- return Response(resp.content, mimetype=resp.headers.get('Content-Type', 'image/jpeg'))
 
 
 
 
 
169
  except Exception as e:
170
  return str(e), 500
171
 
172
- # Background prefetching – we also store the URL that was prefetched.
173
- def prefetch_image_task():
174
- global cached_image, cached_mimetype
175
- # For demonstration, we prefetch one specific image.
176
- # In a more dynamic scenario, you could maintain a dict of URL -> image data.
177
- while True:
178
- # Here, update the URL as needed. For example, if you have default parameters:
179
- url = "http://www.icar-crida.res.in:8080/naip/gisimages/7/2024-25/74_Maxt1.jpg"
180
- try:
181
- response = requests.get(url, timeout=10)
182
- if response.status_code == 200:
183
- cached_image = response.content
184
- cached_mimetype = response.headers.get('Content-Type', 'image/jpeg')
185
- prefetch_image_task.cached_url = url
186
- print("Prefetched image from", url)
187
- else:
188
- print("Failed to prefetch, status code:", response.status_code)
189
- except Exception as ex:
190
- print("Prefetch error:", ex)
191
- time.sleep(300) # Update every 5 minutes
192
-
193
- # Initialize cached_url attribute for our task function.
194
- prefetch_image_task.cached_url = ""
195
-
196
- # Start the background prefetch thread
197
- threading.Thread(target=prefetch_image_task, daemon=True).start()
198
-
199
  if __name__ == '__main__':
200
  app.run(debug=True)
 
1
+ import os
2
+ import hashlib
3
+ import time
4
+ import threading
5
  import requests
6
+ from flask import Flask, render_template, request, jsonify, Response, send_file, url_for
7
  from bs4 import BeautifulSoup
8
  from flask_caching import Cache
9
 
10
  app = Flask(__name__)
11
 
12
+ # Configure in-memory caching for non-image routes
 
13
  app.config['CACHE_TYPE'] = 'SimpleCache'
14
  app.config['CACHE_DEFAULT_TIMEOUT'] = 300 # Cache responses for 5 minutes
15
  cache = Cache(app)
16
 
17
+ # Directory to store cached images
18
+ CACHE_DIR = "cache_images"
19
+ if not os.path.exists(CACHE_DIR):
20
+ os.makedirs(CACHE_DIR)
21
+
22
+ def get_cache_filename(url):
23
+ """Generate a unique filename for a given URL."""
24
+ h = hashlib.md5(url.encode('utf-8')).hexdigest()
25
+ # Here we assume JPEG. You might want to derive extension from url or headers.
26
+ return os.path.join(CACHE_DIR, f"{h}.jpg")
27
 
28
  # Internal mapping of crops to pests (for the form)
29
  CROP_TO_PESTS = {
 
55
 
56
  # Map our internal pest names to external page values per crop.
57
  PEST_MAPPING = {
58
+ "Cotton": {"FallArmyWorm": "71"},
59
+ "Gram": {"H.armigera": "72", "Wilt": "73"},
60
+ "Maize": {"FallArmyWorm": "74"},
61
+ "Rice": {"Blast": "75", "GallMidge": "76", "YSB": "77", "PlantHopper": "78", "BlueBeetle": "79", "BacterialLeafBlight": "80"},
62
+ "Soybean": {"Girdlebeetle": "81", "H.armigera": "82", "Semilooper": "83", "Spodoptera": "84", "StemFLy": "85"},
63
+ "Tur": {"Wilt": "86", "Webbed_Leaves": "87", "Pod_damage": "88"},
64
+ "Sugarcane": {"FallArmyGrub": "89", "WhiteGrub": "90"},
65
+ "Sorgum": {"FallArmyWorm": "91"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
 
68
  # Parameter codes and labels for the final image URL
 
83
  week = request.args.get('week', '')
84
  param = request.args.get('param', '')
85
 
86
+ image_url_param = ""
87
  if crop and pest and year and week and param:
88
  # Build the external image URL (using HTTP)
89
  base_url = f"http://www.icar-crida.res.in:8080/naip/gisimages/{crop}/{year}/{pest}_"
90
  external_image_url = f"{base_url}{param}{week}.jpg"
91
+ # Instead of proxying on every request, pass the external URL to the template.
92
+ image_url_param = external_image_url
93
 
94
  return render_template('index.html',
95
  crops=list(CROP_TO_PESTS.keys()),
 
101
  selected_year=year,
102
  selected_week=week,
103
  selected_param=param,
104
+ image_url_param=image_url_param)
105
 
106
+ # Cache this route based on its query string.
107
  @app.route('/fetch_weeks')
108
  @cache.cached(timeout=300, query_string=True)
109
  def fetch_weeks():
 
134
  weeks = [str(i) for i in range(1, 53)]
135
  return jsonify({"weeks": weeks})
136
 
137
+ # New endpoint to serve a locally cached image file.
138
+ @app.route('/cached-image')
139
+ def cached_image_route():
 
 
140
  external_url = request.args.get('url')
141
+ if not external_url:
142
+ return "Missing URL", 400
143
+
144
+ cache_filename = get_cache_filename(external_url)
145
+ if os.path.exists(cache_filename):
146
+ return send_file(cache_filename, mimetype="image/jpeg")
147
  else:
 
148
  try:
149
  resp = requests.get(external_url, timeout=10)
150
+ if resp.status_code == 200:
151
+ with open(cache_filename, "wb") as f:
152
+ f.write(resp.content)
153
+ return send_file(cache_filename, mimetype=resp.headers.get('Content-Type', 'image/jpeg'))
154
+ else:
155
+ return "Error downloading image", resp.status_code
156
  except Exception as e:
157
  return str(e), 500
158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  if __name__ == '__main__':
160
  app.run(debug=True)