I'm trying to save multiple files, but the Request file() method is returning null. Help-me please
My front end:
<input type="file" name="arquivos" multiple />
External JS:
...
var form = document.forms['frmDados'];
...
In one function:
...
var formData = new FormData();
var ins = form.elements['arquivos'].files.length;
for (var x = 0; x < ins; x++) {
formData.append('arquivos[]', form.elements['arquivos'].files[x]);
}
// https://stackoverflow.com/questions/35192841/fetch-post-with-multipart-form-data
await fetch(window.location.href, {
method: method, // POST or PUT
body: formData,
headers: {
'X-CSRF-Token': form.elements['_token'].value
},
}).then((response) => {
...
My backend:
$arquivos = $request->file('arquivos'); // Illuminate\Http\Request
Log::info($arquivos);
Log::info($request->all());
My laravel.log: (I uploaded 2 files, but only shows 1 in the all() method)
[2020-04-07 14:40:11] local.INFO:
[2020-04-07 14:40:11] local.INFO: array (
'otheratribute' => '3',
'otheratribute2' => '1',
'otheratribute3' => '2020-03-03',
'otheratribute4' => '03:00',
'otheratribute5' => 'Tetandos',
'otheratribute6' => '1',
'otheratribute7' => '2020-04-01',
'arquivos[]' =>
Illuminate\Http\UploadedFile::__set_state(array(
'test' => false,
'originalName' => 'jgcjkpmefepjgcpg.png',
'mimeType' => 'image/png',
'size' => 392328,
'error' => 0,
'hashName' => NULL,
)),
)
What I intend to do:
try {
$infracao->upload($arquivos, true);
} catch (\Exception $e) {
return response($e->getMessage(), 503);
}
UPDATE 07/04/2020 18:21 GMT-3
I forgot to specify, this solution worked for POST Request, but not for PUT Request which is my problem, which is this and my beginning of solution is this.
I'm using the solution as middleware, and the result for the request is what I put in the question.
I think you just need to do
$request->arquivos
instead of
$request->file('arquivos')
And probably you could also do
$request->input('arquivos')
Related
Using this node-ews package, I can send email, but I haven't been able to find a good example of how to read mails from the Inbox folder and get the email's text and attachments.
I've read the Microsoft documentation, such as this one: https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-work-with-exchange-mailbox-items-by-using-ews-in-exchange#get-an-item-by-using-the-ews-managed-api, but the examples are in C#, C++, or VB.
However, I would like to use Nodejs for this.
**I have found a best way extract every content using mailparser. see bellow
// At first Read emails from Inbox
const EWS = require('node-ews');
const simpleParser = require('mailparser').simpleParser;
// exchange server connection info
const ewsConfig = {
username: 'username',
password: 'password',
host: 'hostname'
};
const options = {
rejectUnauthorized: false,
strictSSL: false
};
// initialize node-ews
const ews = new EWS(ewsConfig, options);
var ewsFunction = 'FindItem';
var ewsArgs = {
'attributes': {
'Traversal': 'Shallow'
},
'ItemShape': {
't:BaseShape': 'Default'
},
'ParentFolderIds' : {
'DistinguishedFolderId': {
'attributes': {
'Id': 'inbox'
}
}
}
};
// Itreate over all the emails and store Id and ChangeKey.
ews.run(ewsFunction, ewsArgs, ewsSoapHeader)
.then(result => {
// Iterate over the result and extract Id and ChangeKey of the messages and pass those to GetItem function to read messages
})
// For reading individual messages returned by FindItem (using Id and ChangeKey)
var ewsFunction = 'GetItem';
var ewsArgs = {
'ItemShape': {
'BaseShape': 'Default',
'AdditionalProperties': {
'FieldURI': [
{ 'attributes': { 'FieldURI': 'item:MimeContent'}}
]
}
},
'ItemIds': {
'ItemId': {
'attributes': {
'Id': Id,
'ChangeKey': ChangeKey
}
}
}
};
await ews.run(ewsFunction, ewsArgs, ewsSoapHeader)
.then(result => {
// Iterate over the result and extract meesage
const {Message} = result.ResponseMessages.GetItemResponseMessage.Items
let mimeContent = Buffer.from(Message.MimeContent['$value'], 'base64').toString('binary');// decode mime content
simpleParser(mimeContent).then(async function (mail) {
console.log("mail")
console.log(mail.attachments)
console.log(mail.headers.get('message-id'))
console.log(mail.headers.get('references'))
console.log(mail.headers.get('in-reply-to'))
console.log({
// text: mail.text,
// html: mail.html ? mail.html.replace(/<meta([^>]+)>/g, "") : "",
from: (mail.from) ? mail.from.value.map(item => item.address) : [],
to: (mail.to) ? mail.to.value.map(item => item.address) : [],
cc: (mail.cc) ? mail.cc.value.map(item => item.address) : [],
bcc: (mail.bcc) ? mail.bcc.value.map(item => item.address) : [],
messageId: mail.messageId,
subject: mail.subject
})
}).catch((err) => {
console.log("err")
console.log(err)
})
})
Here you will get the full parsed mail contents with attachments. Happy Coding!!!
I am using React + Laravel. For upload file i using Maatwebsite library. I'm just learning, so all this is for a "home project" :) There is a form with an input for selecting a file and a button:
<form>
<input type="file" name="file" onChange={e => preUploadFile(e)} />
<Button onClick={importFileHandler} disabled={!file}>Upload</Button>
</form>
I save the selected file to the state:
const [file, setFile] = useState(null);
const preUploadFile = e => {
const file = e.target.files[0];
setFile(file);
};
Then I "drop" state into fetch:
// post for import
export const importFileInDataBase = async file => {
try {
const formData = new FormData();
formData.append("file", file);
await fetch(`${url}/v2/organizations/import`, {
method: "POST",
body: formData
}).then(response => {
console.log("result", response);
});
} catch (error) {
console.log(error);
}
};
After that, I call this function by clicking on the button and alsoby clicking on the button I call the function, which will request data from the table with a get request and render it on the page.
const importFileHandler = () => {
new Promise((resolve, reject) => {
resolve(importFileInDataBase(file));
}).then(() => {
getAllOrganizations();
});
};
My Model on the back-end:
class ScheduledInspectionModel extends Model
{
protected $table = 'scheduled_inspection';
protected $fillable = ['name_smp', 'name_control', "verification_start", "verification_end", 'verification_duration'];
public $timestamps = false;
}
Controller:
class OrganizationsImportController extends Controller
{
public function import(Request $request)
{
// return dd($request->file);
Excel::import(new OrganizationsImport, $request->file);
return response()->json('Success upload');
}
}
And file with setting for import:
class OrganizationsImport implements ToModel
{
/**
* #param array $row
*
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new ScheduledInspectionModel([
'name_smp' => $row[0],
'name_control' => $row[1],
'verification_start' => $row[2],
'verification_end' => $row[3],
'verification_duration' => $row[4],
]);
}
}
Please tell me how i can\need to check the type of the imported file (only the .xls file is needed)? PS: another question, I would like to display some message about successful import or not. I in the controller return the message response () -> json ('Import completed'); how can I get use with this? PSS: maybe it comes in handy somehow dd($ response);:
Illuminate\Http\UploadedFile {#282
-test: false
-originalName: "test.xls"
-mimeType: "application/vnd.ms-excel"
-error: 0
#hashName: null
path: "/tmp"
filename: "phpzFcBzS"
basename: "phpzFcBzS"
pathname: "/tmp/phpzFcBzS"
extension: ""
realPath: "/tmp/phpzFcBzS"
aTime: 2020-08-25 14:39:02
mTime: 2020-08-25 14:39:02
cTime: 2020-08-25 14:39:02
inode: 318670
size: 6144
perms: 0100600
owner: 1000
group: 1000
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
You can just use the file input's accept attribute.
<input type="file" name="file" accept=".xls,application/vnd.ms-excel" onChange="..." />
This will only allow you to select .xls files when you click the button.
I am coding a restaurant reviews app with Vue.js and Django REST Framework.
User can "POST" pictures on their reviews.
As soon as the user click a 'Create review' button, this function is triggered:
addReview () {
let endpoint = `/api/restaurant_review/`;
let method = "POST";
apiService(endpoint, method, { maps: this.$route.params.maps, review_author: 1 })
.then(res => {
let review_id = res.id
console.log(review_id)
return review_id
})
},
So I also get a review_id from my response. I pass it to an other component where the user can upload pictures this way:
<ReviewEditor
:id= "review_id"/>
In my data() I have:
review_id: 0,
So in my ReviewEditor component, I get the id like this:
props: {
id: {
type: Number,
required: true
},
}
And then:
onUpload() {
const fd = new FormData();
let axiosConfig = {
headers: {
'X-CSRFTOKEN': CSRF_TOKEN,
}
};
fd.append('picture_1', this.selectedFile)
fd.append('restaurant_review', this.id)
axios.post('http://127.0.0.1:8000/api/outside_pic/', fd, axiosConfig)
.then(res => {
console.log(res)
})
}
My onUpload() function works well if I pass manually the id, but if I do it dynamically with this.id, I have an error message telling me that 'restaurant_id' = 0, and therefore doesn't exists. I also tried review_id: 0, but with no luck either.
I am trying to pass the value in the state as a parameter to the Function.addAddOnData to which calls the setaddOndatatypes function with " addOnCategory" as a parameter, the parameter is not getting passed on doing console.log it shows blank as the response.
First function call:
const onSubmit = e => {
e.preventDefault();
fileUpload(fileInputRef);
if (!state.loading) {
addAddOnDataToDb(
state.addOnCategory,
state.itemName,
state.itemPrice,
state.itemIconURL
);
}
};
Function:
const addAddOnDataToDb = (
itemName,
itemIconURL,
itemPrice,
addOnCategory
) => {
console.log(addOnCategory);
const addOnType = setAddOnItemType(addOnCategory);
console.log(addOnType);
const addOnBody = JSON.stringify({
itemName,
itemIconURL,
itemPrice,
addOnType
});
console.log(addOnBody);
const config = {
headers: {
'Content-Type': 'application/JSON'
}
};
axios.post('/api/v1/addOn', addOnBody, config);
};
Call to setAddOnItemType
const setAddOnItemType = addOnCategory => {
console.log(addOnCategory);
switch (addOnCategory) {
case 'Add on':
return 'addOn';
case 'Flavours':
return 'flavour';
}
};
You have wrong ordering of arguments at the addAddOnDataToDb call side.
you defined the function like:
const addAddOnDataToDb = (
itemName,
itemIconURL,
itemPrice,
addOnCategory
) => {
....
}
And your call looks like:
addAddOnDataToDb(
state.addOnCategory,
state.itemName,
state.itemPrice,
state.itemIconURL
);
state.addOnCategory should be passed as the last argument to the function call. Also the price and icon url are also in wrong order.
addAddOnDataToDb(
state.itemName,
state.itemIconURL,
state.itemPrice,
state.addOnCategory,
);
Premise:
I am creating a page that contains many HTML options with relations like Product-> SubProduct-> Task. Task depends on SubProduct which in-turn depends on Product to Load.
I am repeating my code multiple times in my javascript.
Problem:
I have repeatedly tried to change this code, but I have a multitude of variables. I tried creating a function, but in vain since I am using $each
I accept any suggestions to refactor this code in any capacity.
Code:
$("#ProductId").change(function () {
$("#SubProductId").empty();
$("#TaskId").empty();
$("#SubProductId").append('<option value="0">[Select ...]</option>');
$.ajax({
type: 'POST',
url: urlGetSubProducts,
dataType: 'json',
data: { productId: $("#ProductId").val() },
success: function (data) {
$.each(data, function (i, data) {
$("#SubProductId").append('<option value="'
+ data.SubProductId + '">'
+ data.Name + '</option>');
});
ValidateFilledFields();
},
error: function (ex) {
alert('Fail to find subproduct.' + ex);
}
})
return false;
})
return false;
})
<div>
#Html.LabelFor(m => m.ProductId, "Product")
#Html.DropDownList("ProductId", null, htmlAttributes: new { #class = "form-control", required = "required" })
</div>
Notes:
ProductId is the property id from the HTML above
Proposal:
You can easily design your logic to follow a structured approach like so:
const getCountries = _ => new Promise((res,rej) => $.ajax({
...yourNormalConfigData,
success: res,
fail: rej,
})).then(d => d.countries) // Get contries from response
const getStates = country => new Promise((res,rej) => $.ajax({
url: `/foo/bar/get/States?country=${country}`,
...yourNormalConfigData,
success: res,
fail: rej,
}).then(d => d.states) // Get states from response
const getCities = state => new Promise((res,rej) => $.ajax({
url: `/foo/bar/get/Cities?state=${state}`,
...yourNormalConfigData,
success: res,
fail: rej,
}).then(d => d.cities) // Get cities from response
const injectOptions = elem => arr => {
const html = arr.map(c => `<option>${c}</option>`).join('')
elem.html(html)
}
const el = {
country: $('#Countries'),
state: $('#States'),
city: $('#Cities'),
}
getCountries().then(injectOptions(el.country))
el.country.change(e => {
getStates(el.country.val()).then(injectOptions(el.state))
})
el.state.change(e => {
getCities(el.state.val()).then(injectOptions(el.city))
})
<select id='Countries'>
</select>
<select id='States'>
</select>
<select id='Cities'>
</select>
Notes:
This is leveraging promises, and a ton of code re-use so that you can use the same components to load and configure your data dynamically. I tried not to deviate significantly from your code-base. It also features curried functions for a neater promise logic flow!
The only way to improve that you can make to your code as you have it, is to use string interpolation
$("#VersionId").append(`<option value="
${data.VersionId}">
${data.VersionName}</option>`);
Note: that is omitting the county->state -> city paragraph since is not related with the ajax
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals