Following the documentation I have installed Flask-Upload. when trying to import it: from flask.ext.uploads import UploadSet, IMAGES it raises an error:
Traceback (most recent call last):
File "./run.py", line 3, in <module>
from app import app
File "/home/proj/app/__init__.py", line 38, in <module>
from app.admin.views import admin
File "/home/proj/app/admin/views.py", line 14, in <module>
from flask.ext.uploads import UploadSet, Images
ImportError: cannot import name Images
What is the issue about?
Flask provides a simpler option with out the need for extension. Refer below documentation.
http://flask.pocoo.org/docs/0.10/patterns/fileuploads/
here is my implementation following the details in the link
Imports
import os
from werkzeug import secure_filename
from flask import send_from_directory
#app config
UPLOAD_FOLDER = os.path.dirname(__file__)
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif','doc','docx','xls'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join(UPLOAD_FOLDER,'uploads') # uploads folder should exists in the server
#function that checks the file extension
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
#function that handles the document upload page
#app.route('/input_docs/<contract_id>', methods=['GET', 'POST'])
def input_docs(contract_id):
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], contract_id+'_'+ filename))
else:
flash("Not a valid file %s" % file.filename)
contract = Contracts.query.filter_by(id = contract_id).first()
try:
attachments = [file[file.find('_')+1::] for file in os.listdir(app.config['UPLOAD_FOLDER']) if file.startswith(contract_id+'_')] # Strip out the contract id for from display
except OSError as err:
attachments = []
doc_form = InputDocsForm(obj=contract)
return render_template('input_docs.html',title = 'Input Docs', form=doc_form,attachments=attachments)
function that handles select document download
#app.route('/download_docs/<filename>')
def download_docs(filename):
app.logger.info("Downloading %s"% os.path.join(app.config['UPLOAD_FOLDER'], filename))
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
//client side template
<div class="row">
<div class="span3">
<p><input type=file name=file>
</div>
<div class="span3">
<input type=submit value=Upload>
</div>
<div class="span3">
<input class="btn btn-primary" type="button" value="{{ _('Close') }}">
<input id = 'download' class="btn btn-primary" type="button" value="{{ _('Download') }}">
</div>
</div>
<table class="table">
<thead>
<tr>
<th>Select</th>
<th>Attachment</th>
</tr>
</thead>
<tbody>
{% for attachment in attachments %}
<tr>
<td >{{ attachment }}</td>
<td id = "sel" onclick = 'onSelectDoc( "{{attachment}}" )'> {{ form.sel ( type ="checkbox" ) }} </td>
</tr>
{% endfor %}
</tbody>
</table>
//client side javascript
<script>
var Attachments = [];
$( document ).ready(function(){
$( "#download" ).click(function() {
if (Attachments.length > 0){
var contract_id = document.getElementById('id').value;
var url = flask_util.url_for('download_docs' ,{ filename:contract_id+"_"+Attachments[0] } );
var k = Attachments.length;
while (k--) Attachments.shift();
$(location).attr('href',url);
}
else{
alert("Select at least one attachment to download");
return;
}
});
function onSelectDoc(attachment){
if (attachment.length>0) {
var i = Attachments.indexOf(attachment)
if (i>=0 ) {
Attachments.splice(i,1) ; //remove the attachment on unselect
return;
}
}
Attachments.push(attachment);
}
</script>
Try (notice the omitted dot)
flaskext.uploads import UploadSet, IMAGES
Flask or Flask uploads has changed the path
Edit:
Imports are casesensitive. You should be importing IMAGES instead.
Try this:
pip install -e "git://github.com/FelixLoether/flask-uploads#egg=Flask-Uploads"
Source:
http://flask-uploads.readthedocs.org/en/latest/
Related
I want to upload a file and text from the same page to two Modals. I have created two forms on the same page, one is type=file and the other one is type=text.And two separate button's for each form. And created two Modal Gallery_img and Gallery_txt. when I upload a file, it successfully get uploaded but when I then upload text its is showing error( mentioned below )
Iam Getting error: MultiValueDictKeyError: 'file'
Form:
<form id='form1' action="" method="post" enctype="multipart/form-data" >
{% csrf_token %}
<input type='file' name='file'>
<br>
<button type="submit" onclick='submitForm1()'>Ok</button>
</form>
<br>
<form id='form2' action="" method="post" >
{% csrf_token %}
<input type='text' name='text'>
<br>
<button type="submit" onclick='submitForm2()'> Okay</button>
</form>
//scripts for buttons
<script>
function submitForm1(){
document.getElementById('form1').submit();
};
function submitForm2(){
document.getElementById('form2').submit();
};
</script>
Modals:
class Gallery_img(models.Model):
gallery_image = models.ImageField( upload_to='img',max_length=None)
class Gallery_txt(models.Model):
gallery_text = models.CharField(max_length=8, null=True)
Views:
def gallery(request):
from .models import Gallery_img, Gallery_txt
if request.method== 'POST':
if request.FILES['file']:
post = Gallery_img()
post.gallery_image = request.FILES['file']
post.save()
print('successful image uplaod')
return render(request, 'gallery.html')
if request.POST.get('text'):
post= Gallery_txt()
post.gallery_text = request.POST.get('text')
post.save()
print('successful text uplaod')
return render(request, 'gallery.html')
else:
return render(request, 'gallery.html')
Just edit the views.py
post.gallery_image = request.FILES.get('file')
```
**Below code working fine as expected but getting Id and Password
'undefind&undefind'.**
**I need to show user enter details.Like ID:test and Password;test123
Could you please help me on this.**
**am getting this format.**
http://localhost:8089/api/Logins/CheckPassword?ID=[undefind]&Password=
[undefind
need this format
http://localhost:8089/api/Logins/CheckPassword?ID=[test]&Password=[test123]
```text
Can anyone help me please?
**login.services**
```
getLoginById(UserID: string,Password: string): Observable<Login[]>{
debugger;
let params=new HttpParams().set('ID', UserID).set('Password',Password);
console.log(params.toString());
return this.http.get<Login[]>(this.baseURL,{params});
}
```
**login.component.ts**
```typescript
constructor(
// private formbuilder: FormBuilder,
private loginService: LoginService,
private router:Router,
private route: ActivatedRoute, private formbuilder: FormBuilder)
{}
onFormSubmit() {
this.loading = false;
const client = this.clientForm.value;
this.getLogin(client);
this.clientForm.reset();
}
ngOnInit() {
debugger;
this.clientForm = this.formbuilder.group({
UserID: ['', [Validators.required]],
Password: ['', [Validators.required]]
});
}
getLogin(login :Login){
debugger;
this.loginService.getLoginById(this.clientForm.UserID,this.clientForm.Passwor
d).subscribe(() => {
this.loading = true;
});
}
```
```text
**login.component.html**
```
<div class="container">
<mat-card>
<mat-toolbar color="accent">
<div align="center" style="color:white;text-align:right;">
Login
</div>
</mat-toolbar>
<br>
<br>
<mat-card-content>
<form [formGroup]="clientForm"
(ngSubmit)="onFormSubmit(clientForm.value)">
<table>
<tr>
<td class="tbl1">
<mat-form-field class="demo-full-width">
<input formControlName="UserID" matTooltip="Enter login UserID"
matInput placeholder="UserID">
</mat-form-field>
<mat-error>
<span *ngIf="!clientForm.get('UserID').value &&
clientForm.get('UserID').touched">
</span>
</mat-error>
</td>
</tr>
<tr>
<td class="tbl1">
<mat-form-field class="demo-full-width">
<input formControlName="Password" matTooltip="Enter login
Password" matInput placeholder="Password">
</mat-form-field>
<mat-error>
<span *ngIf="!clientForm.get('Password').value &&
clientForm.get('Password').touched">
</span>
</mat-error>
</td>
</tr>
</table>
<table>
<tr>
<td class="content-center">
<button type="submit" mat-raised-button color="accent"
matTooltip="Click Submit Button" [disabled] =
"!clientForm.valid">Login</button>
<button type="reset" mat-raised-button color="accent"
matTooltip="Click Reset Button" (click) =
"resetForm()">Reset</button>
</td>
</tr>
</table>
</form>
</mat-card-content>
</mat-card>
</div>
```
As Daniel A. White says, it's not a good idea to pass username and password in url parameters as you ask to do.
You'll open a huge security hole and everyone who can intercept your request can stole you your sensitive data.
Anyway if you wish to do this kind of operation, assuming
http://localhost:8089/api/Logins/CheckPassword?ID=[UserID]&Password=[Password]
refers to an endpoint (web api), you have to use this.http.get() this way:
const params: {
'params': {
'ID': userID,
'Password': password
}
};
this.http.get('http://localhost:8089/api/Logins/CheckPassword', params);
My upload code is working good using dropzonejs, and my next task is to create a thumbnail for the image that was uploaded. And so I've used Image Intervention and I was able to create a thumbnail, the only problem I have is when I try to combine the two task in one method, dropzonejs is returning a bunch of html codes. and well, actually everytime I put a return statement in my UploadImage method it returns random html codes. I have read the documentation of dropzonejs and I don't have an idea where the codes coming from. any advice is appreciated. thank you in advance for any help and suggestions.
below are my codes.
Route:
Route::post('uploadimage', 'ProductController#uploadImage');
Controller:
public function uploadImage(Request $request){
//create folder
$products = new Products();
$args['foldername'] = $request->input('folname');
$products->createDirectory($args);
$origName = $request->file('file')->getClientOriginalName();
$request->file('file')->move(public_path().env('FOLDER_NAME_IMAGES').$args['foldername'].'/', $origName );
$this->createThumbnail($request);
}
public function createThumbnail($request){
$origName = $request->file('file')->getClientOriginalName();
$image = new Image();
$file = $request->file('file');
$objImage = $image->make($file->getRealPath());
//create thumbnail
$objImage->save(public_path().env('FOLDER_NAME_IMAGES').'fad611c8-56c7-4a7a-8af9-a2908267f08f'.'/'.$origName)
->resize(200,200) // ->greyscale()
->save(public_path().env('FOLDER_NAME_IMAGES').'fad611c8-56c7-4a7a-8af9-a2908267f08f'.'/'.'thumb-'.$origName);
}
JS code:
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
var myDropzone = new Dropzone(document.body,
{
url: "/uploadimage",
thumbnailWidth: 80,
thumbnailHeight: 80,
parallelUploads: 10,
previewTemplate: previewTemplate,
clickable: ".fileinput-button",
previewsContainer: "#previews",
maxFiles: 10,
maxFilesize: 200, // MB
acceptedFiles: "image/*"
});
myDropzone.on("sending", function(file,xhr,formData) {
// Show the total progress bar when upload starts
var folname = document.getElementById('folname').value;
formData.append('folname',folname);
});
document.querySelector("#actions .cancel").onclick = function() {
myDropzone.removeAllFiles(true);
};
myDropzone.on("removedfile", function(file,xhr,formData) {
var file_name = file.name; //filename of image
var folname = document.getElementById('folname').value;
console.log(folname);
console.log(file_name);
$.ajax({
type: 'POST',
url: '/deleteimage',
data: { 'filename': file_name,'folname': folname },
success: function(report) {
console.log(report);
},
error: function(report) {
console.log(report);
}
});
});
myDropzone.on("addedfile", function(file) {
// Hookup the start button
//get elementbyid set value to previous + 1
var val_pic_count = document.getElementById('pic_count').value;
document.getElementById("pic_count").value = Number(val_pic_count) + 1;
});
HTML code:
<div id="actions">
<div class="btn btn-success fileinput-button">
<span>Add pictures...</span>
</div>
<button type="reset" class="btn btn-warning cancel">
<span>Remove all</span>
</button>
</div> <!--<div id="actions">-->
<input type="hidden" name="pic_count" id="pic_count" value="0">
<span dz-max-files-reached ></span>
<br><br>
<ul class="list-inline">
<li> </li>
<li id="previews">
<div id="template">
<span class="preview"><img data-dz-thumbnail /></span>
<span class="name" data-dz-name></span>
<strong class="error text-danger" data-dz-errormessage></strong>
<span class="pull-right">
<button data-dz-remove class="btn btn-danger delete">
<span>Delete</span>
</button>
</span>
<div style="height: 10px;"></div>
</div>
</li>
<li> </li>
</ul>
Result:
The createThumbnail method is working when i tried it separately.
Okay, found the problem.It's the sequence of my methods and most importantly the variable that is being passed to Intervention object is wrong.
so basically the problem is I was trying to save a file that has already been moved.the createThumbnail method should go first before the saving or moving of the original file.
correct code below.
public function uploadImage(Request $request){
//create folder
$products = new Products();
$args['foldername'] = $request->input('folname');
$products->createDirectory($args);
$origName = $request->file('file')->getClientOriginalName();
$this->createThumbnail($request);
$request->file('file')->move(public_path().env('FOLDER_NAME_IMAGES').$args['foldername'].'/', $origName );
}
and also I found out that in my createThumbnail method, it's not accepting the value of the getRealPath() method.
previous code:
$objImage = $image->make($file->getRealPath());
the right way is to just pass the $file variable
correct code:
$file = $request->file('file');
$objImage = $image->make($file);
and also for the random html codes. it's not random, I just missed reading the bottom part of the codes it's basically the html codes of laravel error page. problem solved.
I'm trying to write a test for file uploading in grails. I'm using spock as my testing framework.
I have a javascript function that link to a button on my view that adds an <input type="file"> to my form whenever it is clicked.
It looks something like this:
<script>
var fileNum = 1;
function addUploader() {
fileNum++;
var fileInputTag = "<input type=\"file\" name=\"myfile." +fileNum+ "\"/>";
var uploadField = document.getElementById("uploadFields");
var row = uploadField.insertRow(fileNum + 1);
var cell = row.insertCell(0);
cell.innerHTML = fileInputTag + "<br/>";
}
</script>
<tr>
<td>
<input type="file" class="required" name="myfile.1" />
</td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td>
More Files <br />
<br/>
<input type="submit" value="Download"/>
</td>
</tr>
My controller looks something like this:
def uploadFile(){
List<MultipartFile> files = []
params.myfile.each {
if (it.value.isEmpty()) {
flash.message = message(code: 'upload.empty.message')
redirect(uri: "/")
return
}
files.add((MultipartFile) it.value)
}
def faxPreviews = []
faxPreviews = uploadFileService.generateFaxPreviews(files)
render(view:'/uploadfile/index', model:[p:uploadFileService.decodeFaxPreviews(faxPreviews)])
}
I want to test that a flash message is shown if the list is empty but I don't know how to put that in the test. I've been trying to search how to mock the view params in the test but so far no go.
This was actually very easy. D'oh! I ended up with this test.
void "updloadFile should warn when no files are attached."() {
given:
def file = new GrailsMockMultipartFile('mockFile', ''.bytes)
Map<MultipartFile> files = [:]
files[1] = file
controller.params.myfile = files
when:
controller.uploadFile()
then:
response.redirectedUrl == '/'
flash.message != null
}
My problem was that I thought the myfile in the view was a key when it is actually the name of a map. So myfile.1 would turn into a myfile[1] = "whatever value is passed to input"
I am still new to Grails. I have an app that has a file upload. I have added this to the controller
def upload = {
def f = request.getFile('myFile')
if(!f.empty) {
f.transferTo( new File("${f.name}") )
response.sendError(200,'Done');
} else {
flash.message = 'file cannot be empty'
render(view:'uploadForm')
}
}
and this is in _forms.gsp
<div class="fieldcontain ${hasErrors(bean: reportInstance, field: 'myFile', 'error')} ">
<label for="myFile">
<g:uploadForm action="upload">
<input type="file" name="myFile"/>
<input type= "submit" value="Upload"/>
</g:uploadForm>
</label>
When I use a g:link to try to retrieve the upload I get redirected and there is nothing displayed
Any advice would be greatly appreciated
g:link I am using
<g:link controller ="Report"
action="listByUserCompany"
>Show first ten ordered by Title</g:link>
class UploadController {
def index() { }
def fileupload () {
def f = request.getFile('myFile')
if(!f.empty) {
f.transferTo( new File("${f.name}") )
render(view:'upload')
}
else {
flash.message = 'file cannot be empty'
render(view:'upload')
}
}
}
<body>
<g:uploadForm name="myUpload" action="fileupload" controller="upload">
<input type="file" name="myFile" />
<input type= "submit" value="Upload"/>
</g:uploadForm>
</body>
i used the above code in my controller and gsp and i made a view named upload in view->upload->upload.gsp .My file uploaded success fully in the root directory of the project itself with name myfile